From: Keir Fraser Date: Thu, 17 Dec 2009 06:27:55 +0000 (+0000) Subject: domctl support for generic memory event handling. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~12879 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success/%22http:/www.example.com/cgi/success?a=commitdiff_plain;h=bd8fd8c198f6a1acc9ac86775977136fdb1ff5a7;p=xen.git domctl support for generic memory event handling. Signed-off-by: Patrick Colp --- diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index ece40141bf..d38b61e303 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -30,6 +30,8 @@ #include /* for arch_do_domctl */ #include #include +#include +#include #ifdef XEN_GDBSX_CONFIG #ifdef XEN_KDB_CONFIG @@ -1299,6 +1301,22 @@ long arch_do_domctl( break; #endif /* XEN_GDBSX_CONFIG */ + case XEN_DOMCTL_mem_event_op: + { + struct domain *d; + + ret = -ESRCH; + d = rcu_lock_domain_by_id(domctl->domain); + if ( d != NULL ) + { + ret = mem_event_domctl(d, &domctl->u.mem_event_op, + guest_handle_cast(u_domctl, void)); + rcu_unlock_domain(d); + copy_to_guest(u_domctl, domctl, 1); + } + } + break; + default: ret = -ENOSYS; break; diff --git a/xen/arch/x86/mm/mem_event.c b/xen/arch/x86/mm/mem_event.c index 0448bd51d9..5701bfee42 100644 --- a/xen/arch/x86/mm/mem_event.c +++ b/xen/arch/x86/mm/mem_event.c @@ -188,6 +188,97 @@ int mem_event_check_ring(struct domain *d) return ring_full; } +int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, + XEN_GUEST_HANDLE(void) u_domctl) +{ + int rc; + + if ( unlikely(d == current->domain) ) + { + gdprintk(XENLOG_INFO, "Tried to do a memory paging op on itself.\n"); + return -EINVAL; + } + + if ( unlikely(d->is_dying) ) + { + gdprintk(XENLOG_INFO, "Ignoring memory paging op on dying domain %u\n", + d->domain_id); + return 0; + } + + if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) ) + { + MEM_EVENT_ERROR("Memory paging op on a domain (%u) with no vcpus\n", + d->domain_id); + return -EINVAL; + } + + /* TODO: XSM hook */ +#if 0 + rc = xsm_mem_event_control(d, mec->op); + if ( rc ) + return rc; +#endif + + if ( mec->mode == 0 ) + { + switch( mec->op ) + { + case XEN_DOMCTL_MEM_EVENT_OP_ENABLE: + { + struct domain *dom_mem_event = current->domain; + struct vcpu *v = current; + unsigned long ring_addr = mec->ring_addr; + unsigned long shared_addr = mec->shared_addr; + l1_pgentry_t l1e; + unsigned long gfn; + p2m_type_t p2mt; + mfn_t ring_mfn; + mfn_t shared_mfn; + + /* Get MFN of ring page */ + guest_get_eff_l1e(v, ring_addr, &l1e); + gfn = l1e_get_pfn(l1e); + ring_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt); + + rc = -EINVAL; + if ( unlikely(!mfn_valid(mfn_x(ring_mfn))) ) + break; + + /* Get MFN of shared page */ + guest_get_eff_l1e(v, shared_addr, &l1e); + gfn = l1e_get_pfn(l1e); + shared_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt); + + rc = -EINVAL; + if ( unlikely(!mfn_valid(mfn_x(shared_mfn))) ) + break; + + rc = -EINVAL; + if ( mem_event_enable(d, ring_mfn, shared_mfn) != 0 ) + break; + + rc = 0; + } + break; + + case XEN_DOMCTL_MEM_EVENT_OP_DISABLE: + { + rc = mem_event_disable(d); + } + break; + + default: + rc = -ENOSYS; + break; + } + } + else + rc = -ENOSYS; + + return rc; +} + /* * Local variables: diff --git a/xen/include/asm-x86/mem_event.h b/xen/include/asm-x86/mem_event.h index 91d6ab3a20..37e3064a37 100644 --- a/xen/include/asm-x86/mem_event.h +++ b/xen/include/asm-x86/mem_event.h @@ -54,6 +54,9 @@ void mem_event_put_request(struct domain *d, mem_event_request_t *req); void mem_event_get_response(struct domain *d, mem_event_response_t *rsp); void mem_event_unpause_vcpus(struct domain *d); +int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec, + XEN_GUEST_HANDLE(void) u_domctl); + #endif /* __MEM_EVENT_H__ */ diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 88b19a4ffe..7a378a3519 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -691,6 +691,31 @@ struct xen_domctl_gdbsx_domstatus { }; +/* + * Memory event operations + */ + +#define XEN_DOMCTL_mem_event_op 56 + +/* Add and remove memory handlers */ +#define XEN_DOMCTL_MEM_EVENT_OP_ENABLE 0 +#define XEN_DOMCTL_MEM_EVENT_OP_DISABLE 1 + +struct xen_domctl_mem_event_op { + uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */ + uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_ENABLE_* */ + + /* OP_ENABLE */ + unsigned long shared_addr; /* IN: Virtual address of shared page */ + unsigned long ring_addr; /* IN: Virtual address of ring page */ + + /* Other OPs */ + unsigned long gfn; /* IN: gfn of page being operated on */ +}; +typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t; +DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t); + + struct xen_domctl { uint32_t cmd; uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */ @@ -734,6 +759,7 @@ struct xen_domctl { struct xen_domctl_set_target set_target; struct xen_domctl_subscribe subscribe; struct xen_domctl_debug_op debug_op; + struct xen_domctl_mem_event_op mem_event_op; #if defined(__i386__) || defined(__x86_64__) struct xen_domctl_cpuid cpuid; #endif